<?php
namespace PsiFramework\Classes\Util\Database\QueryInterpreter;

import("Classes.Util.Database.QueryInterpreter.SqlQueryInterpreter");

use \PsiFramework\Classes\Model\ModelInterface\IPrimitiveObject;
use \PsiFramework\Classes\Util\Database\Query\SqlAddColumn;
use \PsiFramework\Classes\Util\Database\Query\SqlChangeColumnType;
use \PsiFramework\Classes\Util\Database\Query\SqlLimit;
use \psiFramework\Classes\Util\Database\Query\SqlTable;
use \PsiFramework\Classes\Util\Database\Query\SqlType;
use \PsiFramework\Classes\Util\Database\QueryInterpreter\SqlQueryInterpreter;

/**
 * PsiFramework
 * Php Simple Framework
 *
 * @author Rémi San
 * @version beta
 */

/**
 * The MySqlQueryInterpreter is used to translate SqlQueries
 * to string queries for MySql
 *
 * @package Util.QueryInterpreter
 */
class MySqlQueryInterpreter extends SqlQueryInterpreter
{

    protected function getVarDelimiter()
    {
        return '`' ;
    }

    protected function getSqlValue(/*mixed*/ $value)
    {
        if (!is_null($value)) {
            if ($value instanceof IPrimitiveObject) {
                $value = $value->serialize();
            } else if (is_bool($value)) {
                $value = ($value)?"1":"0" ;
            }
            $value = "'".mysql_escape_string($value)."'" ;
        } else {
            $value = 'NULL' ;
        }
        return $value ;
    }

    protected function getLimitClause(SqlLimit $limit=null)
    {
        if (isNullOrEmptyString($limit)) {
            return '' ;
        }
        if (isNullOrEmptyString($limit->getLength())) {
            return '' ;
        }

        $limitString = 'LIMIT ' ;
        if (!isNullOrEmptyString($limit->getSkip())) {
            $limitString .= $limit->getSkip() . ", " ;
        }
        $limitString .= $limit->getLength();

        return $limitString ;
    }

    protected function getChangeColumn(SqlChangeColumnType $parameter=null)
    {
        $stringQuery  = 'MODIFY COLUMN '.
                        $this->getColumnDescription(
                            $parameter->getColumn(),
                            true
                        );

        return $stringQuery ;
    }

    protected function getAddColumn(SqlAddColumn $parameter=null)
    {
        return
            'ADD COLUMN ' .
            $this->getColumnDescription(
                $parameter->getColumn()
            );
    }

    public function getColumnType(
        SqlType $sqlType=null,
        /*bool*/ $includeNullDeclaration=true,
        /*bool*/ $includeLength=true
    )
    {
        $type = null ;
        switch($sqlType->getType()) {
        case SqlType::$serial :
            $type = "INTEGER" ;
            break;
        case SqlType::$integer :
            $type = "INTEGER" ;
            break;
        case SqlType::$float :
            $type = "FLOAT" ;
            break;
        case SqlType::$double :
            $type = "DOUBLE" ;
            break;
        case SqlType::$long :
            $type = "LONG" ;
            break;
        case SqlType::$varchar :
            $type = "VARCHAR" ;
            break;
        case SqlType::$char :
            $type = "CHAR" ;
            break;
        case SqlType::$text :
            $type = "TEXT" ;
            break;
        case SqlType::$date :
        case SqlType::$dateTime :
            $type = "DATETIME" ;
            break;
        case SqlType::$boolean :
            $type = "TINYINT" ;
            break;
        case SqlType::$blob :
            $type = "BLOB" ;
            break;
        }

        if (!isNullOrEmptyString($type)) {
            if (!is_null($sqlType->getLength()) && $includeLength) {
                $type .= '('.$sqlType->getLength().')' ;
            }
            if ($sqlType->getType() == SqlType::$serial && $includeLength) {
                $type .= ' AUTO_INCREMENT' ;
                if ($includeNullDeclaration) {
                    $type .=  'NOT' ;
                }
            } else if (!$sqlType->canBeNull() &&  $includeNullDeclaration) {
                $type .= ' NOT' ;
            }
            if ($includeNullDeclaration) {
                $type .= ' NULL' ;
            }
        }

        return $type ;
    }

    protected function getTableDefinitionSuffix()
    {
        return 'ENGINE=InnoDB DEFAULT CHARSET=utf8' ;
    }

    public static function tableExistsQuery(
        SqlTable $table,
        /*bool*/ $view=false
    )
    {
        $t = 'tables' ;
        if ($view) {
            $t = 'views' ;
        }

        return
            "SELECT COUNT(*) AS `table_exists` ".
            "FROM `information_schema`.`".$t."` ".
            "WHERE `table_schema` = '".$table->getSchema()."' ".
            "AND `table_name` = '".$table->getName()."'" ;
    }

    public static function tableStructureQuery(SqlTable $table)
    {
        return
            "SELECT ".
                "`COLUMN_NAME` AS `name`, ".
                "`IS_NULLABLE` AS `nullable`, ".
                "`DATA_TYPE` AS `type`, ".
                "`CHARACTER_MAXIMUM_LENGTH` AS `length`, ".
                "`COLUMN_DEFAULT` AS `default`, ".
                "`EXTRA` AS `extra` ".
            "FROM `information_schema`.`columns` ".
            "WHERE `table_schema` = '".$table->getSchema()."' ".
            "AND `table_name` = '".$table->getName()."'" ;
    }

}
